﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.Win32;

namespace Macaw.Spf2010.ResourceListSolution
{
    [Guid("4349A4B9-C669-49FF-B358-9F723020B5FF")]
    public class LoggingService : SPDiagnosticsServiceBase
    {
        public static class Categories
        {
            public static string ResourceListReader = "ResourceListReader";
            public static string Features = "Features";
        }

        public static LoggingService Local
        {
            get { return SPFarm.Local.Services.GetValue<LoggingService>(DefaultName); }
        }

        public static string DefaultName
        {
            get { return "Macaw.Spf2010.ResourceListSolution Logging Service"; }
        }

        public static string AreaName
        {
            get { return "Macaw.Spf2010.ResourceListSolution"; }
        }

        public LoggingService()
            : base(DefaultName, SPFarm.Local)
        {
        }

        protected override IEnumerable<SPDiagnosticsArea> ProvideAreas()
        {
            List<SPDiagnosticsArea> areas = new List<SPDiagnosticsArea>
         {
				new SPDiagnosticsArea(AreaName, 0, 0, false, new List<SPDiagnosticsCategory>
				{
				    new SPDiagnosticsCategory(Categories.ResourceListReader, null, TraceSeverity.Verbose, EventSeverity.Information, 0, 0, false, true),
                    new SPDiagnosticsCategory(Categories.Features, null, TraceSeverity.Verbose, EventSeverity.Information, 0, 0, false, true)
				})
        };

            return areas;
        }

        public static void WriteTrace(string categoryName, TraceSeverity traceSeverity, string format, params string[] arg)
        {
            WriteTrace(categoryName, traceSeverity, string.Format(format, arg));
        }

        public static void WriteTrace(string categoryName, TraceSeverity traceSeverity, string message)
        {
            // NOTE: If the given value in the severity parameter is less than the currently configured value for 
            // the category's TraceSeverity property, the trace is not written to the log.

            if (string.IsNullOrEmpty(message))
                return;

            try
            {
                LoggingService service = Local;

                if (service != null)
                {
                    SPDiagnosticsCategory category = service.Areas[AreaName].Categories[categoryName];
                    service.WriteTrace(1, category, traceSeverity, message);
                }
            }
            catch { }
        }

        public static void WriteEvent(string categoryName, EventSeverity eventSeverity, string format, params string[] arg)
        {
            WriteEvent(categoryName, eventSeverity, string.Format(format, arg));
        }

        public static void WriteEvent(string categoryName, EventSeverity eventSeverity, string message)
        {
            if (string.IsNullOrEmpty(message))
                return;

            try
            {
                LoggingService service = Local;

                if (service != null)
                {
                    SPDiagnosticsCategory category = service.Areas[AreaName].Categories[categoryName];
                    service.WriteEvent(1, category, eventSeverity, message);
                }
            }
            catch { }
        }


        private const string EventLogApplicationRegistryKeyPath = @"SYSTEM\CurrentControlSet\services\eventlog\Application";

        public static void RegisterLoggingService(SPFarm farm)
        {
            if (farm != null)
            {
                LoggingService service = LoggingService.Local;

                if (service == null)
                {
                    service = new LoggingService();
                    service.Update();

                    if (service.Status != SPObjectStatus.Online)
                        service.Provision();
                }

                foreach (SPServer server in farm.Servers)
                {
                    RegistryKey baseKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, server.Address);

                    if (baseKey != null)
                    {
                        RegistryKey eventLogKey = baseKey.OpenSubKey(EventLogApplicationRegistryKeyPath, true);

                        if (eventLogKey != null)
                        {
                            RegistryKey loggingServiceKey = eventLogKey.OpenSubKey(LoggingService.AreaName);

                            if (loggingServiceKey == null)
                            {
                                loggingServiceKey = eventLogKey.CreateSubKey(LoggingService.AreaName, RegistryKeyPermissionCheck.ReadWriteSubTree);
                                loggingServiceKey.SetValue("EventMessageFile", @"C:\Windows\Microsoft.NET\Framework\v2.0.50727\EventLogMessages.dll", RegistryValueKind.String);
                            }
                        }
                    }
                }
            }
        }

        public static void UnRegisterLoggingService(SPFarm farm)
        {
            if (farm != null)
            {
                LoggingService service = LoggingService.Local;

                if (service != null)
                    service.Delete();

                foreach (SPServer server in farm.Servers)
                {
                    RegistryKey baseKey = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, server.Address);

                    if (baseKey != null)
                    {
                        RegistryKey eventLogKey = baseKey.OpenSubKey(EventLogApplicationRegistryKeyPath, true);

                        if (eventLogKey != null)
                        {
                            RegistryKey loggingServiceKey = eventLogKey.OpenSubKey(LoggingService.AreaName);

                            if (loggingServiceKey != null)
                                eventLogKey.DeleteSubKey(LoggingService.AreaName);
                        }
                    }
                }
            }
        }


    }

}
